/*
 * @描述: 
 * @创建者: kilomChou
 * @Date: 2021-05-09 13:38:05
 * @最后编辑: kilomChou
 * @LastEditTime: 2021-05-15 16:00:47
 */
import BaseWorldManager from "./BaseWorldManager";
import World from "../World";
import Chunk from "../Chunk";
import Food, { FoodType, IFoodInit } from "../Food";
import { RandUtil } from "../../../util/RandUtil";
import { Util } from "../../../util/Util";
import { VWorld } from "../../../data/XlsxVo";
import { Vec2 } from "../../../core/vec2/Vec2";
const [util, ru, v2] = [Util, RandUtil, Vec2];

/** 世界食物管理器 */
export default class WorldFoodMgr extends BaseWorldManager {

    constructor(world: World) {
        super(world);
        this.foodMap.set(FoodType.normal, new Set());
        this.foodMap.set(FoodType.snake, new Set());
    }

    /** 食物映射 FoodType->Set<Food> */
    readonly foodMap = new Map<FoodType, Set<Food>>()
    /** 被吃的食物id映射 foodId->eaterId  */
    readonly eatenFoodIdMap = new Map<number, number>();

    /** 当前食物唯一标识 */
    private _curFoodId: number = 1;
    /** 可创建食物的区块数组 */
    private _createFoodChunks: Chunk[] = [];
    /** 普通食物的数量 */
    private _normalFoodCount = 0;

    start() {
        this.timer.set(key_createFoods, VWorld.cfg.createFoodsTime, 0);
        this.timer.set(key_clearSnakeFoods, VWorld.cfg.clearFoodsTime);
        this._createFoodChunks = this.world.chunks.concat();
        //创建最大数量的普通食物
        this.createNormalFoods(VWorld.cfg.foodMax);
    }

    update() {
        this.createNormalFoods();
        this.clearSnakeFoods();
    }

    /** 创建指定数量的普通食物到世界 */
    createNormalFoods(count?: number) {
        this.timer.check(key_createFoods, () => {
            //计算创建数量
            count = count || VWorld.cfg.createFoodCount + this.world.snakeMgr.snakeMap.size * VWorld.cfg.createFoodCount2;
            //随机创建食物
            while (count && this._normalFoodCount < VWorld.cfg.foodMax && this._createFoodChunks.length) {
                let chunk = ru.choice(this._createFoodChunks);
                let food = this.createFood(v2.setPos(tmpFoodInit,
                    ru.rand(chunk.x - this.world.chunkRadius.w, chunk.x + this.world.chunkRadius.w),
                    ru.rand(chunk.y - this.world.chunkRadius.h, chunk.y + this.world.chunkRadius.h)
                ));
                if (food.isLive) {
                    //isLive代表创建成功
                    count--;
                    this._normalFoodCount++;
                    if (++food.chunk.normalFoodCount >= VWorld.cfg.chunkFoodMax) {
                        //超出区块最大食物容纳数量从可创建食物的区块数组中移除
                        util.arrRemoveItem(this._createFoodChunks, chunk);
                    }
                }
            }
        }, (extra) => -extra);
    }

    /** 定期清除战利品食物 */
    clearSnakeFoods() {
        this.timer.check(key_clearSnakeFoods, time => {
            this.foodMap.get(FoodType.snake).forEach(food => {
                if (time >= food.clearTime) {
                    this.removeFood(food);
                }
            })
        })
    }

    /** 创建食物 */
    createFood(init: IFoodInit, addToWorld = true) {
        let food = foodPool.pop() || new Food(this.world);
        food.init(init);
        addToWorld && this.addFood(food);
        return food;
    }

    /** 添加食物到世界区块 true:添加成功 false:撞墙销毁*/
    addFood(food: Food) {
        if (this.world.isCirColWall(food)) {
            //撞墙不添加，回收食物
            foodPool.push(food);
            return false;
        } else {
            //添加成功
            food.id = this._curFoodId++;
            //添加到区块中
            food.chunks = this.world.getChunks(food);
            food.chunks.forEach(chunk => chunk.addFood(food));
            //添加到食物映射中
            this.foodMap.get(food.type).add(food);
            food.onAdded();
            return true;
        }
    }

    /** 从世界区块中移除食物 */
    removeFood(food: Food, eaterId?: number) {
        food.isLive = false;
        //从区块中移除
        food.chunks.forEach(chunk => chunk.removeFood(food));
        if (food.type == FoodType.normal) {
            this._normalFoodCount--;
            if (--food.chunk.normalFoodCount == VWorld.cfg.chunkFoodMax - 1) {
                //普通食物数量回到容纳阈值重新添加到可创建食物区块数组中去
                this._createFoodChunks.push(food.chunk);
            }
        }
        //从食物映射中移除
        this.foodMap.get(food.type).delete(food);
        //记录被吃的食物
        eaterId && this.eatenFoodIdMap.set(food.id, eaterId);
        //回收
        foodPool.push(food);
    }
}

/** 食物对象池 */
const foodPool: Food[] = [];
/** 生成食物的定时器key */
const key_createFoods = "foodMgr_createFoods";
/** 定时清除战利品食物的定时器key */
const key_clearSnakeFoods = "foodMgr_clearSnakeFoods";
/** createNormalFoods()专用 */
const tmpFoodInit: IFoodInit = { x: 0, y: 0, r: 0, ang: 0 };